/**
 * @copyright 2025 银杏ERP
 * @author 银杏ERP
 * @version 1.0
 * @license http://www.hhyx.xyz
 * @developer Lhf
 */

namespace app\admin\service\yxerp;

use think\facade\Db;
use think\facade\Event;
use app\admin\model\yxerp\Inventory;
use app\admin\model\yxerp\InventoryLog;
use app\admin\model\yxerp\WarehouseOperation;
use app\admin\model\yxerp\WarehouseOperationDetail;

class InventoryService
{
    /**
     * 处理入库操作
     *
     * @param WarehouseOperation $operation 入库单据
     * @return bool
     * @throws \Exception
     */
    public static function processInbound($operation)
    {
        if ($operation['status'] != 2 || $operation['direction'] != 1) {
            throw new \Exception('只能处理已审核的入库单据');
        }
        
        Db::startTrans();
        try {
            // 获取完整的入库单及明细
            $operation = WarehouseOperation::with(['details'])->where('id', $operation['id'])->find();
            if (!$operation) {
                throw new \Exception('入库单据不存在');
            }
            
            // 处理每个明细
            foreach ($operation['details'] as $detail) {
                // 查找库存记录
                $inventory = Inventory::where([
                    'warehouse_id' => $operation['warehouse_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: ''
                ])->find();
                
                $beforeQuantity = 0;
                
                // 如果不存在，创建新的库存记录
                if (!$inventory) {
                    $inventory = new Inventory();
                    $inventory->warehouse_id = $operation['warehouse_id'];
                    $inventory->product_id = $detail['product_id'];
                    $inventory->batch_no = $detail['batch_no'] ?: '';
                    $inventory->location_id = $detail['location_id'];
                    $inventory->unit_id = $detail['unit_id'];
                    $inventory->unit_name = $detail['unit_name'];
                    $inventory->production_date = $detail['production_date'];
                    $inventory->expiry_date = $detail['expiry_date'];
                    $inventory->quantity = 0;
                    $inventory->cost_price = $detail['price'];
                    $inventory->status = 1; // 正常状态
                } else {
                    $beforeQuantity = $inventory->quantity;
                    // 更新成本价（可以考虑加权平均等方法）
                    $inventory->cost_price = $detail['price'];
                }
                
                // 更新库存数量
                $inventory->quantity += $detail['quantity'];
                $inventory->save();
                
                // 记录库存变动日志
                InventoryLog::recordLog([
                    'warehouse_id' => $operation['warehouse_id'],
                    'location_id' => $detail['location_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: '',
                    'operation_type' => $operation['operation_type'],
                    'operation_name' => $operation['operation_name'],
                    'direction' => 1, // 入库
                    'quantity' => $detail['quantity'],
                    'before_quantity' => $beforeQuantity,
                    'after_quantity' => $inventory->quantity,
                    'unit_name' => $detail['unit_name'],
                    'operation_id' => $operation['id'],
                    'operation_detail_id' => $detail['id'],
                    'source_type' => $operation['source_type'],
                    'source_id' => $operation['source_id'],
                    'source_no' => $operation['source_no'],
                    'remark' => $detail['remark'],
                    'create_user_id' => $operation['approve_user_id'],
                    'create_user' => $operation['approve_user']
                ]);
            }
            
            // 触发入库完成事件
            Event::trigger('warehouse_inbound_completed', $operation);
            
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }
    
    /**
     * 处理出库操作
     *
     * @param WarehouseOperation $operation 出库单据
     * @return bool
     * @throws \Exception
     */
    public static function processOutbound($operation)
    {
        if ($operation['status'] != 2 || $operation['direction'] != 2) {
            throw new \Exception('只能处理已审核的出库单据');
        }
        
        Db::startTrans();
        try {
            // 获取完整的出库单及明细
            $operation = WarehouseOperation::with(['details'])->where('id', $operation['id'])->find();
            if (!$operation) {
                throw new \Exception('出库单据不存在');
            }
            
            // 处理每个明细
            foreach ($operation['details'] as $detail) {
                // 查找库存记录
                $inventory = Inventory::where([
                    'warehouse_id' => $operation['warehouse_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: ''
                ])->find();
                
                // 检查库存是否足够
                if (!$inventory || $inventory->quantity < $detail['quantity']) {
                    throw new \Exception('产品'.$detail['product_name'].'库存不足，无法出库');
                }
                
                $beforeQuantity = $inventory->quantity;
                
                // 更新库存数量
                $inventory->quantity -= $detail['quantity'];
                $inventory->save();
                
                // 记录库存变动日志
                InventoryLog::recordLog([
                    'warehouse_id' => $operation['warehouse_id'],
                    'location_id' => $detail['location_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: '',
                    'operation_type' => $operation['operation_type'],
                    'operation_name' => $operation['operation_name'],
                    'direction' => 2, // 出库
                    'quantity' => $detail['quantity'],
                    'before_quantity' => $beforeQuantity,
                    'after_quantity' => $inventory->quantity,
                    'unit_name' => $detail['unit_name'],
                    'operation_id' => $operation['id'],
                    'operation_detail_id' => $detail['id'],
                    'source_type' => $operation['source_type'],
                    'source_id' => $operation['source_id'],
                    'source_no' => $operation['source_no'],
                    'remark' => $detail['remark'],
                    'create_user_id' => $operation['approve_user_id'],
                    'create_user' => $operation['approve_user']
                ]);
            }
            
            // 触发出库完成事件
            Event::trigger('warehouse_outbound_completed', $operation);
            
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }
    
    /**
     * 处理反入库操作（取消入库的影响）
     *
     * @param WarehouseOperation $operation 入库单据
     * @return bool
     * @throws \Exception
     */
    public static function processReverseInbound($operation)
    {
        if ($operation['direction'] != 1) {
            throw new \Exception('只能处理入库单据');
        }
        
        Db::startTrans();
        try {
            // 获取完整的入库单及明细
            $operation = WarehouseOperation::with(['details'])->where('id', $operation['id'])->find();
            if (!$operation) {
                throw new \Exception('入库单据不存在');
            }
            
            // 处理每个明细
            foreach ($operation['details'] as $detail) {
                // 查找库存记录
                $inventory = Inventory::where([
                    'warehouse_id' => $operation['warehouse_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: ''
                ])->find();
                
                // 检查库存是否足够
                if (!$inventory || $inventory->quantity < $detail['quantity']) {
                    throw new \Exception('产品'.$detail['product_name'].'当前库存不足，无法反入库');
                }
                
                $beforeQuantity = $inventory->quantity;
                
                // 更新库存数量
                $inventory->quantity -= $detail['quantity'];
                $inventory->save();
                
                // 记录库存变动日志
                InventoryLog::recordLog([
                    'warehouse_id' => $operation['warehouse_id'],
                    'location_id' => $detail['location_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: '',
                    'operation_type' => $operation['operation_type'],
                    'operation_name' => $operation['operation_name'] . '(反入库)',
                    'direction' => 2, // 作为出库处理
                    'quantity' => $detail['quantity'],
                    'before_quantity' => $beforeQuantity,
                    'after_quantity' => $inventory->quantity,
                    'unit_name' => $detail['unit_name'],
                    'operation_id' => $operation['id'],
                    'operation_detail_id' => $detail['id'],
                    'source_type' => $operation['source_type'],
                    'source_id' => $operation['source_id'],
                    'source_no' => $operation['source_no'],
                    'remark' => '反入库操作',
                    'create_user_id' => $operation['approve_user_id'],
                    'create_user' => $operation['approve_user']
                ]);
            }
            
            // 触发反入库完成事件
            Event::trigger('warehouse_reverse_inbound_completed', $operation);
            
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }
    
    /**
     * 处理反出库操作（取消出库的影响）
     *
     * @param WarehouseOperation $operation 出库单据
     * @return bool
     * @throws \Exception
     */
    public static function processReverseOutbound($operation)
    {
        if ($operation['direction'] != 2) {
            throw new \Exception('只能处理出库单据');
        }
        
        Db::startTrans();
        try {
            // 获取完整的出库单及明细
            $operation = WarehouseOperation::with(['details'])->where('id', $operation['id'])->find();
            if (!$operation) {
                throw new \Exception('出库单据不存在');
            }
            
            // 处理每个明细
            foreach ($operation['details'] as $detail) {
                // 查找库存记录
                $inventory = Inventory::where([
                    'warehouse_id' => $operation['warehouse_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: ''
                ])->find();
                
                $beforeQuantity = 0;
                
                // 如果不存在，创建新的库存记录
                if (!$inventory) {
                    $inventory = new Inventory();
                    $inventory->warehouse_id = $operation['warehouse_id'];
                    $inventory->product_id = $detail['product_id'];
                    $inventory->batch_no = $detail['batch_no'] ?: '';
                    $inventory->location_id = $detail['location_id'];
                    $inventory->unit_id = $detail['unit_id'];
                    $inventory->unit_name = $detail['unit_name'];
                    $inventory->production_date = $detail['production_date'];
                    $inventory->expiry_date = $detail['expiry_date'];
                    $inventory->quantity = 0;
                    $inventory->cost_price = $detail['price'];
                    $inventory->status = 1; // 正常状态
                } else {
                    $beforeQuantity = $inventory->quantity;
                }
                
                // 更新库存数量
                $inventory->quantity += $detail['quantity'];
                $inventory->save();
                
                // 记录库存变动日志
                InventoryLog::recordLog([
                    'warehouse_id' => $operation['warehouse_id'],
                    'location_id' => $detail['location_id'],
                    'product_id' => $detail['product_id'],
                    'batch_no' => $detail['batch_no'] ?: '',
                    'operation_type' => $operation['operation_type'],
                    'operation_name' => $operation['operation_name'] . '(反出库)',
                    'direction' => 1, // 作为入库处理
                    'quantity' => $detail['quantity'],
                    'before_quantity' => $beforeQuantity,
                    'after_quantity' => $inventory->quantity,
                    'unit_name' => $detail['unit_name'],
                    'operation_id' => $operation['id'],
                    'operation_detail_id' => $detail['id'],
                    'source_type' => $operation['source_type'],
                    'source_id' => $operation['source_id'],
                    'source_no' => $operation['source_no'],
                    'remark' => '反出库操作',
                    'create_user_id' => $operation['approve_user_id'],
                    'create_user' => $operation['approve_user']
                ]);
            }
            
            // 触发反出库完成事件
            Event::trigger('warehouse_reverse_outbound_completed', $operation);
            
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }
} 